package com.jastar.android.tts;

import android.content.Context;
import android.media.MediaPlayer;
import android.util.Log;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import okhttp3.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.Date;

/**
 * 百度TTS管理器
 */
public class BaiduTTSManager {
    private static BaiduTTSManager instance;
    private OkHttpClient httpClient;
    private MediaPlayer mediaPlayer;
    private String accessToken;
    private Context context;
    private File cacheDir;
    private static final long CACHE_MAX_AGE = 7 * 24 * 60 * 60 * 1000L; // 缓存7天
    private static final long CACHE_MAX_SIZE = 50 * 1024 * 1024L; // 最大缓存50MB

    public interface TTSListener {
        default void onStart() {
        }

        default void onDone() {
        }

        default void onError(String error) {
        }
    }

    private BaiduTTSManager(Context context) {
        this.context = context.getApplicationContext();
        init(context);
    }

    public static synchronized BaiduTTSManager initInstance(Context context) {
        if (instance == null) instance = new BaiduTTSManager(context);
        return instance;
    }

    public static BaiduTTSManager getInstance() {
        return instance;
    }

    private void init(Context context) {
        httpClient = new OkHttpClient();
        mediaPlayer = new MediaPlayer();
        cacheDir = new File(context.getCacheDir(), "tts_cache");
        if (!cacheDir.exists()) cacheDir.mkdirs();
        refreshAccessToken();
        cleanExpiredCache(); // 启动时清理过期缓存
    }

    /**
     * 生成文本的MD5哈希作为缓存文件名
     */
    private String getCacheFileName(String text, String per) {
        String combinedKey = text + "_" + per;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hash = md.digest(combinedKey.getBytes("UTF-8"));
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                hexString.append(String.format("%02x", b));
            }
            return hexString + ".mp3";
        } catch (Exception e) {
            return (combinedKey).hashCode() + ".mp3";
        }
    }

    /**
     * 检查缓存是否存在且未过期
     */
    private boolean isCacheValid(String text, String per) {
        File cacheFile = new File(cacheDir, getCacheFileName(text, per));
        if (!cacheFile.exists()) {
            return false;
        }

        long lastModified = cacheFile.lastModified();
        long currentTime = new Date().getTime();
        return (currentTime - lastModified) < CACHE_MAX_AGE;
    }

    /**
     * 从缓存播放音频
     */
    private boolean playFromCache(String text, String per, TTSListener listener) {
        try {
            File cacheFile = new File(cacheDir, getCacheFileName(text, per));
            if (!cacheFile.exists()) {
                return false;
            }

            mediaPlayer.reset();
            mediaPlayer.setDataSource(cacheFile.getAbsolutePath());
            mediaPlayer.prepareAsync();

            mediaPlayer.setOnPreparedListener(mp -> {
                Log.i("BaiduTTS", "从缓存播放: " + text);
                mp.start();
            });

            mediaPlayer.setOnCompletionListener(mp -> {
                if (listener != null) listener.onDone();
            });

            mediaPlayer.setOnErrorListener((mp, what, extra) -> {
                Log.e("BaiduTTS", "缓存播放错误: what=" + what + ", extra=" + extra);
                // 缓存文件可能损坏，删除它
                cacheFile.delete();
                if (listener != null) listener.onError("播放错误");
                return true;
            });

            return true;
        } catch (Exception e) {
            Log.e("BaiduTTS", "缓存播放失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 保存音频到缓存
     */
    private void saveToCache(String text, String per, byte[] audioData) {
        try {
            // 检查缓存大小，如果超过限制则清理
            if (getCacheSize() > CACHE_MAX_SIZE) {
                cleanOldestCache();
            }

            File cacheFile = new File(cacheDir, getCacheFileName(text, per));
            try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
                fos.write(audioData);
                fos.flush();
            }
            Log.i("BaiduTTS", "音频已缓存: " + text);
        } catch (Exception e) {
            Log.e("BaiduTTS", "缓存保存失败: " + e.getMessage());
        }
    }

    /**
     * 获取当前缓存大小
     */
    private long getCacheSize() {
        long size = 0;
        File[] files = cacheDir.listFiles();
        if (files != null) {
            for (File file : files) {
                size += file.length();
            }
        }
        return size;
    }

    /**
     * 清理最旧的缓存文件
     */
    private void cleanOldestCache() {
        File[] files = cacheDir.listFiles();
        if (files != null && files.length > 0) {
            File oldestFile = files[0];
            for (File file : files) {
                if (file.lastModified() < oldestFile.lastModified()) {
                    oldestFile = file;
                }
            }
            oldestFile.delete();
            Log.i("BaiduTTS", "清理最旧缓存: " + oldestFile.getName());
        }
    }

    /**
     * 清理过期缓存
     */
    private void cleanExpiredCache() {
        File[] files = cacheDir.listFiles();
        if (files != null) {
            long currentTime = new Date().getTime();
            int cleanedCount = 0;
            for (File file : files) {
                if ((currentTime - file.lastModified()) > CACHE_MAX_AGE) {
                    if (file.delete()) {
                        cleanedCount++;
                    }
                }
            }
            if (cleanedCount > 0) {
                Log.i("BaiduTTS", "清理过期缓存: " + cleanedCount + " 个文件");
            }
        }
    }

    private void refreshAccessToken() {
        RequestBody formBody = new FormBody.Builder().add("grant_type", "client_credentials").add("client_id", BaiduTTSConfig.API_KEY).add("client_secret", BaiduTTSConfig.SECRET_KEY).build();

        Request request = new Request.Builder().url(BaiduTTSConfig.TOKEN_URL).post(formBody).build();

        httpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e("BaiduTTS", "获取Token失败: " + e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    String responseBody = response.body().string();
                    JsonObject jsonObject = JsonParser.parseString(responseBody).getAsJsonObject();

                    if (jsonObject.has("access_token")) {
                        accessToken = jsonObject.get("access_token").getAsString();
                        Log.i("BaiduTTS", "Token获取成功");
                    }
                }
            }
        });
    }

    public void speak(String text, String specPer, TTSListener listener) {
        if (accessToken == null) {
            Log.w("BaiduTTS", "Token未就绪");
            if (listener != null) listener.onError("服务未就绪");
            return;
        }

        String per = null != specPer ? specPer : BaiduTTSConfig.PERS[0];
        String spd = BaiduTTSConfig.SPD; // 默认语速
        String pit = BaiduTTSConfig.PIT; // 默认音调

        // 1. 先检查缓存
        if (isCacheValid(text, per)) {
            if (playFromCache(text, per, listener)) {
                return; // 缓存播放成功，直接返回
            }
        }

        // 2. 缓存不存在或无效，从网络获取
        if (listener != null) listener.onStart();

        // 判断文本是英文还是中文，选择合适的语言参数
        String lang = "zh";
        if (text.matches(".*[a-zA-Z].*")) {
            lang = "en";
        }

        // 调整参数以更适合小朋友学习
        // 对于中文文本
        if (lang.equals("zh")) {
            // 减慢语速，适合小朋友倾听和模仿
            spd = "3";
            // 稍微提高音调，听起来更亲切友好
            pit = "7";
        }
        // 对于英文文本
        else if (lang.equals("en")) {
            // 英文语速也稍微减慢
            spd = "3";
            // 英文音调保持适中
            pit = "5";
        }

        RequestBody formBody = new FormBody.Builder().add("tex", text).add("lan", lang).add("tok", accessToken).add("ctp", "1").add("cuid", "jastar_tv").add("per", per)  // 添加发音人参数
                .add("spd", spd)  // 添加语速参数
                .add("pit", pit)  // 添加音调参数
                .add("vol", BaiduTTSConfig.VOL)  // 添加音量参数
                .add("aue", BaiduTTSConfig.AUE)  // 添加音频格式参数
                .build();

        Request request = new Request.Builder().url(BaiduTTSConfig.TTS_URL).post(formBody).build();

        httpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e("BaiduTTS", "请求失败: " + e.getMessage());
                if (listener != null) listener.onError("网络错误");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful() && response.body() != null) {
                    byte[] audioData = response.body().bytes();
                    // 保存到缓存
                    saveToCache(text, per, audioData);
                    // 播放音频
                    playFromCache(text, per, listener);
                    // playAudio(audioData, listener); // 先直接用缓存，实测如果有异步问题，切回这个
                } else {
                    Log.e("BaiduTTS", "响应错误: " + response.code());
                    if (listener != null) listener.onError("服务错误");
                }
            }
        });
    }

    private void playAudio(byte[] audioData, TTSListener listener) {
        try {
            mediaPlayer.reset();

            // 创建临时文件播放
            File tempFile = File.createTempFile("tts_audio", ".mp3", context.getCacheDir());
            try (FileOutputStream fos = new FileOutputStream(tempFile)) {
                fos.write(audioData);
                fos.flush();
            }

            mediaPlayer.setDataSource(tempFile.getAbsolutePath());
            mediaPlayer.prepareAsync();

            mediaPlayer.setOnPreparedListener(mp -> {
                mp.start();
                tempFile.deleteOnExit();
            });

            mediaPlayer.setOnCompletionListener(mp -> {
                if (listener != null) listener.onDone();
            });

            mediaPlayer.setOnErrorListener((mp, what, extra) -> {
                Log.e("BaiduTTS", "播放错误: what=" + what + ", extra=" + extra);
                if (listener != null) listener.onError("播放错误");
                return true;
            });

        } catch (Exception e) {
            Log.e("BaiduTTS", "播放失败: " + e.getMessage());
            if (listener != null) listener.onError("播放失败");
        }
    }

    /**
     * 手动清理所有缓存
     */
    public void clearCache() {
        File[] files = cacheDir.listFiles();
        if (files != null) {
            int clearedCount = 0;
            for (File file : files) {
                if (file.delete()) {
                    clearedCount++;
                }
            }
            Log.i("BaiduTTS", "手动清理缓存: " + clearedCount + " 个文件");
        }
    }

    /**
     * 获取缓存统计信息
     */
    public String getCacheStats() {
        File[] files = cacheDir.listFiles();
        int fileCount = files != null ? files.length : 0;
        long totalSize = getCacheSize();
        return String.format("缓存文件: %d 个, 总大小: %.2f MB", fileCount, totalSize / 1024.0 / 1024.0);
    }

    public void shutdown() {
        if (mediaPlayer != null) {
            mediaPlayer.release();
        }
        instance = null;
    }

}